{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "48941c99",
   "metadata": {},
   "source": [
    "# Impedance, admittance and scattering analysis\n",
    "### Prerequisite\n",
    "You need to have a working local installation of Ansys."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "31117997",
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, Headings\n",
    "import pyEPR as epr"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a730d65",
   "metadata": {},
   "source": [
    "## 1. Create the design in Metal\n",
    "Set up a design of a given dimension. Dimensions will be respected in the design rendering. <br>\n",
    "Note that the design will be centered in the origin, will thus equally extend in all quadrants."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f655f8a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "design = designs.DesignPlanar({}, True)\n",
    "design.chips.main.size['size_x'] = '2mm'\n",
    "design.chips.main.size['size_y'] = '2mm'\n",
    "\n",
    "gui = MetalGUI(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "014f9883",
   "metadata": {},
   "source": [
    "Create a single transmon with one readout resonator. It will show in the center of the previously defined chip."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c374a1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "design.delete_all_components()\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options =  dict(\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    connection_pads=dict(\n",
    "        readout = dict(loc_W=+1,loc_H=+1, pad_width='200um')\n",
    "    )))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55bddc4c",
   "metadata": {},
   "source": [
    "## 2. Eigenmode and Impedance analysis using the analysis package - most users\n",
    "\n",
    "#### Setup\n",
    "\n",
    "Select the analysis you intend to run from the `qiskit_metal.analyses` collection.<br>\n",
    "Select the design to analyze and the tool to use for any external simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4d426de",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.simulation import ScatteringImpedanceSim\n",
    "em1 = ScatteringImpedanceSim(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e7e1a14",
   "metadata": {},
   "source": [
    "Review and update the setup. For driven modal you will need to define not only the simulation convergence parameters, but also the frequency sweep.\n",
    "\n",
    "Customizable parameters and default values:\n",
    "* freq_ghz=5 (simulation frequency)\n",
    "* name=\"Setup\" (setup name)\n",
    "* max_delta_s=0.1 (absolute value of maximum difference in scattering parameter S)\n",
    "* max_passes=10 (maximum number of passes)\n",
    "* min_passes=1 (minimum number of passes)\n",
    "* min_converged=1 (minimum number of converged passes)\n",
    "* pct_refinement=30 (percent refinement)\n",
    "* basis_order=1 (basis order)\n",
    "* vars (global variables to set in the renderer)\n",
    "* sweep_setup (all the parameters of the sweep)\n",
    " * name=\"Sweep\" (name of sweep)\n",
    " * start_ghz=2.0 (starting frequency)\n",
    " * stop_ghz=8.0 (stopping frequency)\n",
    " * count=101 (total number of frequencies)\n",
    " * step_ghz=None (frequency step size)\n",
    " * type=\"Fast\" (type of sweep)\n",
    " * save_fields=False (whether or not to save fields)\n",
    " \n",
    "The following two cells will give you an example on how to update the setup."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc2495f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de44cad4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# example: update single setting\n",
    "em1.setup.max_passes = 12\n",
    "em1.setup.sweep_setup.stop_ghz = 13\n",
    "# example: update multiple settings\n",
    "em1.setup_update(max_delta_s = 0.15, freq_ghz = 5.2)\n",
    "\n",
    "em1.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae8d41f6",
   "metadata": {},
   "source": [
    "#### Execute simulation and observe the Impedence\n",
    "Analyze a single qubit with shorted terminations. Assign lumped ports on the readout and on the junction. Then observe the impedance plots.\n",
    "\n",
    "Here, pin Q1_a is converted into a lumped port with an impedance of 70 Ohms. <br>\n",
    "Meanwhile, the central junction Q1_rect_jj is rendered as both a port and an inductor with an impedance of 50 Ohms and an inductance of 10 nH, respectively.\n",
    "\n",
    "The 10nH inductance value is taken from the component option `hfss_inductance` (And the component options find their way in the QGeometry tables by rebuilding). So let's demonstrate how to update the inductance of the junction in the next cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "830b26af",
   "metadata": {},
   "outputs": [],
   "source": [
    "q1.options.hfss_inductance='11nH'\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "903aa3a6",
   "metadata": {},
   "source": [
    "Now we can run the simulation with the newly set `11 nH` value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1cb20a5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.run(name=\"SingleTM\", components=[], open_terminations=[], port_list=[('Q1', 'readout', 70)],\n",
    "           jj_to_port=[('Q1', 'rect_jj', 50, True)], box_plus_buffer = False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7fcd12c",
   "metadata": {},
   "source": [
    "The last variables you pass to the `run()` or `run_sim()` methods, will be stored in the `setup` dictionary under the key `run`. You can recall the information passed by either accessing the dictionary directly, or by using the print handle below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd33f406",
   "metadata": {},
   "outputs": [],
   "source": [
    "# em1.setup.run    <- direct access\n",
    "em1.print_run_args()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94e9bc46",
   "metadata": {},
   "source": [
    "(optional) Captures the renderer GUI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d6e00145",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b20bd592",
   "metadata": {},
   "source": [
    "(optional) if you ever feel the need to remind yourself which project, design, and setup is currently active (connected to qiskit-metal) you can use the following lines."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d0c9ad87",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"\"\"\n",
    "project_name = {em1.renderer.pinfo.project_name}\n",
    "design_name  = {em1.renderer.pinfo.design_name}\n",
    "setup_name   = {em1.renderer.pinfo.setup_name}\n",
    "\"\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b13286c9",
   "metadata": {},
   "source": [
    "Finally, you can plot the various parameters. The semicolon at the end of the cell can be used to suppress the inline return."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b1aae4dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.get_impedance();  # default: ['Z11', 'Z21']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d8772f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.get_admittance();  # default: ['Y11', 'Y21']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b89439c",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.get_scattering();  # default: ['S11', 'S21', 'S22']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cfb53a5b",
   "metadata": {},
   "source": [
    "Finally, disconnect from Ansys."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bbbe3e5b",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5100f60",
   "metadata": {},
   "source": [
    "## 3. Directly access the renderer to modify other parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7945111",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.start()\n",
    "em1.renderer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff625c0c",
   "metadata": {},
   "source": [
    "Every renderer will have its own collection of methods. Below an example with hfss."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b618c2a5",
   "metadata": {},
   "source": [
    "##### Prepare and run a collection of predefined setups\n",
    "\n",
    "This is equivalent to going to the Project Manager panel in Ansys, right clicking on Analysis within the active HFSS design, selecting \"Add Solution Setup...\", and choosing/entering default values in the resulting popup window. You might want to do this to keep track of different solution setups, giving each of them a different/specific name."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e57db5d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "setup = em1.renderer.new_ansys_setup(name = \"Setup_demo\", max_passes = 6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a506488",
   "metadata": {},
   "source": [
    "You can directly pass to `new_ansys_setup` all the setup parameters. Of course you will then need to run the individual setups by name as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a3ebd0a",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.renderer.analyze_setup(setup.name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3aa6617",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
